package net.aiotos.common.dto;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import net.aiotos.common.exception.*;
import lombok.Data;
import lombok.SneakyThrows;

import java.io.Serializable;
import java.util.Collections;
import java.util.List;


/**
 * 接收服务器JSON数据对象,并映谢成实例对象
 */
@Data
public class ResultDTO implements Serializable {

    /**
     * 原始JSON返回字条串
     */
    public final String rawJson;
    /**
     * 状态码
     */
    private ErrorEnum code = null;
    /**
     * 处理结果描述
     */
    private String msg = null;
    /**
     * 返回数据对象
     */
    private JSON data = null;
    private static final long serialVersionUID = -3821339130160848360L;

    public ResultDTO(String rawJson, ErrorEnum code, String msg, JSON data) {
        this.rawJson = rawJson;
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    public ResultDTO(Integer code, String msg, JSON data) {
        this.rawJson = null;
        this.code = ErrorEnum.valueOf(code);
        this.msg = msg;
        this.data = data;
    }

    public ResultDTO(Integer code, String msg) {
        this.rawJson = null;
        this.code = ErrorEnum.valueOf(code);
        this.msg = msg;
    }

    public ResultDTO() {
        this.rawJson = null;
    }

    /**
     * 将JSON对象映谢为目前对象
     * @param tClass 目前对象
     * @param <T>
     * @return
     */
    public <T> T toJavaObject(Class<T> tClass) {
        return JSONObject.toJavaObject(data, tClass);
    }

    public <T> List<T> toJavaArray(Class<T> tClass) {
        return ((JSONArray)data).toJavaList(tClass);
    }

    public static <T> T toJavaObject(String jsonStr, Class<T> tClass) {
        return JSONObject.parseObject(jsonStr, tClass);
    }

    public static <T> List<T> toJavaArray(String jsonStr, Class<T> tClass) {
        return JSONArray.parseArray(jsonStr, tClass);
    }

    /**
     * 将JSON字符转换成对象
     * @param jsonStr
     * @return
     */
    @SneakyThrows
    public static ResultDTO toObject(String jsonStr)  {
        JSONObject jsonObject = null;
        try {
            Object object = JSON.parse(jsonStr);
            if(object instanceof JSONObject) {
                jsonObject = JSONObject.parseObject(jsonStr);
            } else {
                JSONArray jsonArray = JSONArray.parseArray(jsonStr);
                if(jsonArray.get(0) instanceof JSONObject) {
                    jsonObject = jsonArray.getJSONObject(0);
                } else {
                    String format = String.format("返回JSON格式异常：%s", jsonStr);
                    throw new Exception(format);
                }
            }
        } catch (JSONException ex) {
            System.out.println(jsonStr);
            throw ex;
        }

        Integer code = null;
        String msg = null;
        JSONObject data = null;

        if(jsonObject.containsKey("code")) {
            code = jsonObject.getInteger("code");
        }
        if(jsonObject.containsKey("msg")) {
            msg = jsonObject.getString("msg");
        }
        if(jsonObject.containsKey("data")) {
            Object object = jsonObject.get("data");
            if(object instanceof String) {

            } else if(object instanceof JSONObject) {
                data = jsonObject.getJSONObject("data");
            } else {

            }

        }
        return new ResultDTO(jsonStr, ErrorEnum.valueOf(code), msg, data);
    }

    /**
     * 将JSON字符转换成列表对象, 兼容data值非对象的返回情况（data:"xxxxx"）
     * @param jsonStr
     * @return
     */
    public static List<ResultDTO> toArray(String jsonStr) {
        try {
            return JSONArray.parseArray(jsonStr, ResultDTO.class);
        } catch (Exception ex) {
            List<ResultErrorDTO> resultErrorDTOS = JSONArray.parseArray(jsonStr, ResultErrorDTO.class);
            ResultDTO resultDTO = new ResultDTO();
            ResultErrorDTO resultErrorDTO = resultErrorDTOS.get(0);
            resultDTO.setCode(resultErrorDTO.getCode());
            resultDTO.setMsg(resultErrorDTO.getMsg());
            return Collections.singletonList(resultDTO);
        }

    }

    public static ResultDTO code(int code) {
        ResultDTO resultDTO = new ResultDTO();
        resultDTO.code = ErrorEnum.valueOf(code);
        return resultDTO;
    }

    public static ResultDTO code(ErrorEnum code) {
        ResultDTO resultDTO = new ResultDTO();
        resultDTO.code = code;
        return resultDTO;
    }

    public static ResultDTO ret(int code, String msg, Object data) {
        return new ResultDTO(code, msg, (JSON) JSONObject.toJSON(data));
    }

    public static ResultDTO ret(int code, String msg, JSON data) {
        return new ResultDTO(code, msg, data);
    }

    public static ResultDTO ret(int code, String msg) {
        return new ResultDTO(code, msg);
    }

    public void setCode(ErrorEnum code) {
        this.code = code;
    }

    public ResultDTO msg(String msg) {
        this.msg = msg;
        return this;
    }

    public ResultDTO data(DataDTO dataDTO) {
        this.data = (JSON) JSONObject.toJSON(dataDTO);
        return this;
    }

    @Override
    public String toString() {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code", code.code);
        jsonObject.put("data", data);
        jsonObject.put("msg", msg);
        return jsonObject.toJSONString();
    }

    /**
     * 异常检测，统一处理非0返回void
     */
    public void check() throws Exception {
        if(code == ErrorEnum.NotDriver) {
            return;
        }
        if(code == ErrorEnum.Successfull) {
            return;
        }

        if(code == ErrorEnum.SelfOffline) {
            throw new SelfOfflineError();
        }
        if(code == ErrorEnum.AccountNotRegister) {
            throw new AccountNotRegisterError();
        }
        if(code == ErrorEnum.IONodeNotExist) {
            throw new IONodeNotExistError();
        }
        if(code == ErrorEnum.DataNotExist) {
            throw new DataNotExistError("");
        }
        if(code == ErrorEnum.RequestNotAuth) {
            throw new RequestNotAuthError("");
        }
//        if(code == ErrorEnum.Unknown) {
//            throw new Exception("未定义:" + rawJson);
//        }
        throw new Exception(rawJson);
    }
}
